#include "stdafx.h"
#include "jc.h"

static size_t stream_sizes[] = {
	0x20, 0x40, 0x80, 
	0x100,0x200, 0x400, 0x800,
	0x1000,0x2000,0x3000,0x5000,0x8000,0xc000,
	0x12000,0x1b000,0x29000,0x3e000,0x5d000,0x8c000,0xd2000,
	0x13b000,0x1d9000,0x2c6000,0x429000,0x63e000,0x95d000,0xe0c000,
	0x1512000,0x1f9b000,0x2f69000,0x471e000,0x6aad000,0xa004000,0xf006000,
	0x16809000,0x21c0e000,0x32a15000,0x4bf20000,0x71eb0000,0xaae08000,
#ifdef _WIN64
	0x10050c000,0x180792000,0x240b5b000,0x361109000,0x51198e000,0x79a655000,0xb67980000,
	0x111b640000,0x19a9160000,0x267da10000,0x39bc718000,0x569aaa4000,0x81e7ff6000,0xc2dbff1000,
	0x12449fea000,0x1b66efdf000,0x291a67cf000,0x3da79bb7000,0x5c7b6993000,0x8ab91e5d000,0xd015ad8c000,
	0x138208452000,0x1d430c67b000,0x2be4929b9000,0x41d6dbe96000,0x62c249de1000,0x94236ecd2000,0xde352633b000,
	0x14d4fb94d9000,0x1f3f795f46000,0x2edf360ee9000,0x464ed1165e000,0x697639a18d000,0x9e31567254000,0xed4a01ab7e000,
	0x163ef02813d000,0x215e683c1dc000,0x320d9c5a2ca000,0x4b146a8742f000,0x709e9fcae47000,0xa8edefb056b000,0xfd64e788821000,
	0x17c175b4cc32000,0x23a2308f324b000,0x357348d6cb71000,0x502ced42312a000,0x784363e349bf000,0xb46515d4ee9f000,
	0x10e97a0bf65ef000,0x195e3711f18e7000,0x260d529aea55b000,0x3913fbe85f809000,0x559df9dc8f40e000,0x806cf6cad6e15000,0xc0a3723042520000,
#endif
	};

JStream::JStream(void)
	:m_data(NULL), m_capacity(0), m_length(0), m_position(0)
{
}

JStream::~JStream(void)
{
	if(m_data)
	{
		free(m_data);
		m_data = NULL;
		m_capacity = 0;
		m_length = 0;
		m_position = 0;
	}
}

void JStream::ensure(size_t len)
{
	void *ptr;
	size_t capacity = 0;

	if(len <= m_capacity)
		return;

	for(int i=0;i<sizeof(stream_sizes)/sizeof(stream_sizes[0]);i++)
	{
		if(len <= stream_sizes[i])
		{
			capacity = stream_sizes[i];
			break;
		}
	}

	if(capacity == 0)
		THROW_JEXCEPTION(L"Except memory length is too long: %Iu.", len);

	ptr = realloc(m_data, capacity);
	if(!ptr)
		THROW_JEXCEPTION(L"Alloc memory failed, except length %Iu.", capacity);

	m_capacity = capacity;
	m_data = (unsigned char *)ptr;
}

void JStream::setLength(size_t len)
{
	if(len == 0)
		clear();
	else
	{
		ensure(len);
		m_length = len;
	}
}

void JStream::clear(void)
{
	if(m_data)
	{
		free(m_data);
		m_data = NULL;
		m_capacity = 0;
		m_length = 0;
		m_position = 0;
	}
}

void JStream::write(const void *data, size_t len)
{
	if(data == NULL || len == 0)
		return;

	ensure(m_position + len);

	memcpy(m_data + m_position, data, len);
	m_position += len;
	if(m_length < m_position)
		m_length = m_position;
}

#if _DEBUG
#include <stdio.h>

void cctv()
{
	THROW_JEXCEPTION_WIN(3, L"Alloc memory failed, except length %Iu.", (size_t)100);
}

#include <hash_map>
void JStream::Test(void)
{
	JStream js;
	js.write("AOOL Buffer::Ensuro", 19);
	js.write("BOOL Buffer::Ensure", 19);

	
}
#endif
